home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
lisp
/
kcl
/
akcl
/
kcl.lha
/
c
/
num_comp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1987-06-04
|
6KB
|
304 lines
/*
(c) Copyright Taiichi Yuasa and Masami Hagiya, 1984. All rights reserved.
Copying of this file is authorized to users who have executed the true and
proper "License Agreement for Kyoto Common LISP" with SIGLISP.
*/
/*
Comparisons on numbers
*/
#include "include.h"
#include "num_include.h"
/*
The value of number_compare(x, y) is
-1 if x < y
0 if x = y
1 if x > y.
If x or y is complex, 0 or 1 is returned.
*/
int
number_compare(x, y)
object x, y;
{
int i;
double dx, dy;
vs_mark;
switch (type_of(x)) {
case t_fixnum:
switch (type_of(y)) {
case t_fixnum:
if (fix(x) < fix(y))
return(-1);
else if (fix(x) == fix(y))
return(0);
else
return(1);
case t_bignum:
i = big_sign((struct bignum *)y);
if (i < 0)
return(1);
else
return(-1);
case t_ratio:
x = number_times(x, y->rat.rat_den);
y = y->rat.rat_num;
vs_push(x);
i = number_compare(x, y);
vs_reset;
return(i);
case t_shortfloat:
dx = (double)(fix(x));
dy = (double)(sf(y));
goto LONGFLOAT;
case t_longfloat:
dx = (double)(fix(x));
dy = lf(y);
goto LONGFLOAT;
case t_complex:
goto Y_COMPLEX;
default:
wrong_type_argument(Snumber, y);
}
case t_bignum:
switch (type_of(y)) {
case t_fixnum:
i = big_sign((struct bignum *)x);
if (i < 0)
return(-1);
else
return(1);
case t_bignum:
return(big_compare((struct bignum *)x,
(struct bignum *)y));
case t_ratio:
x = number_times(x, y->rat.rat_den);
y = y->rat.rat_num;
vs_push(x);
i = number_compare(x, y);
vs_reset;
return(i);
case t_shortfloat:
dx = number_to_double(x);
dy = (double)(sf(y));
goto LONGFLOAT;
case t_longfloat:
dx = number_to_double(x);
dy = lf(y);
goto LONGFLOAT;
case t_complex:
goto Y_COMPLEX;
default:
wrong_type_argument(Snumber, y);
}
case t_ratio:
switch (type_of(y)) {
case t_fixnum:
case t_bignum:
y = number_times(y, x->rat.rat_den);
x = x->rat.rat_num;
vs_push(y);
i = number_compare(x, y);
vs_reset;
return(i);
case t_ratio:
vs_push(number_times(x->rat.rat_num,y->rat.rat_den));
vs_push(number_times(y->rat.rat_num,x->rat.rat_den));
i = number_compare(vs_top[-2], vs_top[-1]);
vs_reset;
return(i);
case t_shortfloat:
dx = number_to_double(x);
dy = (double)(sf(y));
goto LONGFLOAT;
case t_longfloat:
dx = number_to_double(x);
dy = lf(y);
goto LONGFLOAT;
case t_complex:
goto Y_COMPLEX;
default:
wrong_type_argument(Snumber, y);
}
case t_shortfloat:
dx = (double)(sf(x));
goto LONGFLOAT0;
case t_longfloat:
dx = lf(x);
LONGFLOAT0:
switch (type_of(y)) {
case t_fixnum:
dy = (double)(fix(y));
goto LONGFLOAT;
case t_bignum:
case t_ratio:
dy = number_to_double(y);
goto LONGFLOAT;
case t_shortfloat:
dy = (double)(sf(y));
goto LONGFLOAT;
case t_longfloat:
dy = lf(y);
goto LONGFLOAT;
case t_complex:
goto Y_COMPLEX;
}
LONGFLOAT:
if (dx == dy)
return(0);
else if (dx < dy)
return(-1);
else
return(1);
Y_COMPLEX:
if (number_zerop(y->cmp.cmp_imag))
if (number_compare(x, y->cmp.cmp_real) == 0)
return(0);
else
return(1);
else
return(1);
case t_complex:
if (type_of(y) != t_complex)
if (number_zerop(x->cmp.cmp_imag))
if (number_compare(x->cmp.cmp_real, y) == 0)
return(0);
else
return(1);
else
return(1);
if (number_compare(x->cmp.cmp_real, y->cmp.cmp_real) == 0 &&
number_compare(x->cmp.cmp_imag, y->cmp.cmp_imag) == 0 )
return(0);
else
return(1);
default:
FEwrong_type_argument(Snumber, x);
}
}
Lall_the_same()
{
int narg, i;
narg = vs_top - vs_base;
if (narg == 0)
too_few_arguments();
for (i = 0; i < narg; i++)
check_type_number(&vs_base[i]);
for (i = 1; i < narg; i++)
if (number_compare(vs_base[i-1], vs_base[i]) != 0) {
vs_top = vs_base+1;
vs_base[0] = Cnil;
return;
}
vs_top = vs_base+1;
vs_base[0] = Ct;
}
Lall_different()
{
int narg, i, j;
narg = vs_top - vs_base;
if (narg == 0)
too_few_arguments();
else if (narg == 1) {
vs_base[0] = Ct;
return;
}
for (i = 0; i < narg; i++)
check_type_number(&vs_base[i]);
for(i = 1; i < narg; i++)
for(j = 0; j < i; j++)
if (number_compare(vs_base[j], vs_base[i]) == 0) {
vs_top = vs_base+1;
vs_base[0] = Cnil;
return;
}
vs_top = vs_base+1;
vs_base[0] = Ct;
}
Lnumber_compare(s, t)
int s, t;
{
int narg, i;
narg = vs_top - vs_base;
if (narg == 0)
too_few_arguments();
for (i = 0; i < narg; i++)
check_type_or_rational_float(&vs_base[i]);
for (i = 1; i < narg; i++)
if (s*number_compare(vs_base[i], vs_base[i-1]) < t) {
vs_top = vs_base+1;
vs_base[0] = Cnil;
return;
}
vs_top = vs_base+1;
vs_base[0] = Ct;
}
Lmonotonically_increasing() { Lnumber_compare( 1, 1); }
Lmonotonically_decreasing() { Lnumber_compare(-1, 1); }
Lmonotonically_nondecreasing() { Lnumber_compare( 1, 0); }
Lmonotonically_nonincreasing() { Lnumber_compare(-1, 0); }
Lmax()
{
object max;
int narg, i;
narg = vs_top - vs_base;
if (narg == 0)
too_few_arguments();
for (i = 0; i < narg; i++)
check_type_or_rational_float(&vs_base[i]);
for (i = 1, max = vs_base[0]; i < narg; i++)
if (number_compare(max, vs_base[i]) < 0)
max = vs_base[i];
vs_top = vs_base+1;
vs_base[0] = max;
}
Lmin()
{
object min;
int narg, i;
narg = vs_top - vs_base;
if (narg == 0)
too_few_arguments();
for (i = 0; i < narg; i++)
check_type_or_rational_float(&vs_base[i]);
for (i = 1, min = vs_base[0]; i < narg; i++)
if (number_compare(min, vs_base[i]) > 0)
min = vs_base[i];
vs_top = vs_base+1;
vs_base[0] = min;
}
init_num_comp()
{
make_function("=", Lall_the_same);
make_function("/=", Lall_different);
make_function("<", Lmonotonically_increasing);
make_function(">", Lmonotonically_decreasing);
make_function("<=", Lmonotonically_nondecreasing);
make_function(">=", Lmonotonically_nonincreasing);
make_function("MAX", Lmax);
make_function("MIN", Lmin);
}